"""
SimpleAPI ORM 数据库迁移

提供简化的数据库迁移功能，封装复杂的迁移操作。
"""

import os
import json
import asyncio
from typing import List, Dict, Any, Optional
from datetime import datetime
from tortoise import Tortoise
from .database import database
import logging

logger = logging.getLogger(__name__)


class Migration:
    """迁移类"""
    
    def __init__(self, name: str, version: str = None):
        """
        初始化迁移
        
        Args:
            name: 迁移名称
            version: 迁移版本
        """
        self.name = name
        self.version = version or datetime.now().strftime("%Y%m%d_%H%M%S")
        self.operations = []
        
    def create_table(self, model_class) -> 'Migration':
        """
        添加创建表操作
        
        Args:
            model_class: 模型类
            
        Returns:
            迁移实例
        """
        self.operations.append({
            "type": "create_table",
            "model": model_class.__name__,
            "table": model_class._meta.db_table
        })
        return self
        
    def drop_table(self, model_class) -> 'Migration':
        """
        添加删除表操作
        
        Args:
            model_class: 模型类
            
        Returns:
            迁移实例
        """
        self.operations.append({
            "type": "drop_table",
            "model": model_class.__name__,
            "table": model_class._meta.db_table
        })
        return self
        
    def add_column(self, model_class, field_name: str, field_type: str) -> 'Migration':
        """
        添加列操作
        
        Args:
            model_class: 模型类
            field_name: 字段名
            field_type: 字段类型
            
        Returns:
            迁移实例
        """
        self.operations.append({
            "type": "add_column",
            "model": model_class.__name__,
            "table": model_class._meta.db_table,
            "field_name": field_name,
            "field_type": field_type
        })
        return self
        
    def drop_column(self, model_class, field_name: str) -> 'Migration':
        """
        删除列操作
        
        Args:
            model_class: 模型类
            field_name: 字段名
            
        Returns:
            迁移实例
        """
        self.operations.append({
            "type": "drop_column",
            "model": model_class.__name__,
            "table": model_class._meta.db_table,
            "field_name": field_name
        })
        return self
        
    def execute_sql(self, sql: str, params: List = None) -> 'Migration':
        """
        添加执行 SQL 操作
        
        Args:
            sql: SQL 语句
            params: 参数列表
            
        Returns:
            迁移实例
        """
        self.operations.append({
            "type": "execute_sql",
            "sql": sql,
            "params": params or []
        })
        return self
        
    def to_dict(self) -> Dict:
        """转换为字典"""
        return {
            "name": self.name,
            "version": self.version,
            "operations": self.operations,
            "created_at": datetime.now().isoformat()
        }


class MigrationManager:
    """迁移管理器"""
    
    def __init__(self, migrations_dir: str = "migrations"):
        """
        初始化迁移管理器
        
        Args:
            migrations_dir: 迁移文件目录
        """
        self.migrations_dir = migrations_dir
        self._ensure_migrations_dir()
        
    def _ensure_migrations_dir(self) -> None:
        """确保迁移目录存在"""
        if not os.path.exists(self.migrations_dir):
            os.makedirs(self.migrations_dir)
            
    def create_migration(self, name: str) -> Migration:
        """
        创建新迁移
        
        Args:
            name: 迁移名称
            
        Returns:
            迁移实例
        """
        return Migration(name)
        
    def save_migration(self, migration: Migration) -> str:
        """
        保存迁移到文件
        
        Args:
            migration: 迁移实例
            
        Returns:
            迁移文件路径
        """
        filename = f"{migration.version}_{migration.name}.json"
        filepath = os.path.join(self.migrations_dir, filename)
        
        with open(filepath, 'w', encoding='utf-8') as f:
            json.dump(migration.to_dict(), f, indent=2, ensure_ascii=False)
            
        logger.info(f"迁移已保存: {filepath}")
        return filepath
        
    def load_migration(self, filepath: str) -> Migration:
        """
        从文件加载迁移
        
        Args:
            filepath: 迁移文件路径
            
        Returns:
            迁移实例
        """
        with open(filepath, 'r', encoding='utf-8') as f:
            data = json.load(f)
            
        migration = Migration(data["name"], data["version"])
        migration.operations = data["operations"]
        return migration
        
    def list_migrations(self) -> List[str]:
        """
        列出所有迁移文件
        
        Returns:
            迁移文件列表
        """
        if not os.path.exists(self.migrations_dir):
            return []
            
        files = []
        for filename in os.listdir(self.migrations_dir):
            if filename.endswith('.json'):
                files.append(os.path.join(self.migrations_dir, filename))
                
        return sorted(files)
        
    async def apply_migration(self, migration: Migration) -> None:
        """
        应用迁移
        
        Args:
            migration: 迁移实例
        """
        database._ensure_initialized()
        
        logger.info(f"应用迁移: {migration.name}")
        
        for operation in migration.operations:
            await self._execute_operation(operation)
            
        logger.info(f"迁移 {migration.name} 应用完成")
        
    async def _execute_operation(self, operation: Dict) -> None:
        """
        执行迁移操作
        
        Args:
            operation: 操作字典
        """
        op_type = operation["type"]
        
        if op_type == "create_table":
            # 创建表操作通过 generate_schemas 处理
            await Tortoise.generate_schemas(safe=True)
            
        elif op_type == "drop_table":
            # 删除表
            table_name = operation["table"]
            await database.execute_sql(f"DROP TABLE IF EXISTS {table_name}")
            
        elif op_type == "add_column":
            # 添加列（简化实现）
            table_name = operation["table"]
            field_name = operation["field_name"]
            field_type = operation["field_type"]
            await database.execute_sql(
                f"ALTER TABLE {table_name} ADD COLUMN {field_name} {field_type}"
            )
            
        elif op_type == "drop_column":
            # 删除列（简化实现）
            table_name = operation["table"]
            field_name = operation["field_name"]
            await database.execute_sql(
                f"ALTER TABLE {table_name} DROP COLUMN {field_name}"
            )
            
        elif op_type == "execute_sql":
            # 执行 SQL
            sql = operation["sql"]
            params = operation.get("params", [])
            await database.execute_sql(sql, params)
            
        else:
            logger.warning(f"未知的迁移操作类型: {op_type}")
            
    async def apply_all_migrations(self) -> None:
        """应用所有迁移"""
        migration_files = self.list_migrations()
        
        for filepath in migration_files:
            migration = self.load_migration(filepath)
            await self.apply_migration(migration)
            
    async def create_initial_migration(self) -> Migration:
        """
        创建初始迁移
        
        Returns:
            初始迁移实例
        """
        migration = Migration("initial")
        
        # 添加所有模型的创建表操作
        for app_name, app_models in Tortoise.apps.items():
            for model_name, model_class in app_models.items():
                if not getattr(model_class._meta, 'abstract', False):
                    migration.create_table(model_class)
                    
        return migration


# 全局迁移管理器
migration_manager = MigrationManager()


# 便捷函数
async def create_tables() -> None:
    """创建所有表"""
    await database.create_tables()


async def drop_tables() -> None:
    """删除所有表"""
    await database.drop_tables()


async def migrate() -> None:
    """应用所有迁移"""
    await migration_manager.apply_all_migrations()


def make_migration(name: str) -> Migration:
    """创建新迁移"""
    return migration_manager.create_migration(name)


def save_migration(migration: Migration) -> str:
    """保存迁移"""
    return migration_manager.save_migration(migration) 